package framework.units;

import framework.utils.UUIDUtil;

import java.math.BigInteger;
import java.util.UUID;

/**
 * 基础数字编码器
 */
public class BaseCoder {
    private final char[] CHARS;

    public BaseCoder(String CHARS) {
        if (CHARS == null || CHARS.length() < 2) {
            throw new IllegalArgumentException("baseChars length must > 1");
        }
        this.CHARS = CHARS.toCharArray();
    }

    public String encode(long number) {
        if (number == 0) {
            return String.valueOf(CHARS[0]);
        }

        StringBuilder sb = new StringBuilder();
        while (number > 0) {
            int remainder = (int) (number % CHARS.length);
            sb.append(CHARS[remainder]);
            number = number / CHARS.length;
        }
        return sb.reverse().toString();
    }

    public long decode(String encoded) {
        long result = 0;
        for (int i = 0; i < encoded.length(); i++) {
            char c = encoded.charAt(i);
            int digit = indexOf(c);
            if (digit == -1) {
                throw new IllegalArgumentException("invalid chars: " + c);
            }
            result = result * CHARS.length + digit;
        }
        return result;
    }

    private int indexOf(char c) {
        for (int i = 0; i < CHARS.length; i++) {
            if (CHARS[i] == c) {
                return i;
            }
        }
        return -1;
    }

    /**
     * 将byte数组编码
     */
    public String bytesEncode(byte[] input) {
        if (input.length == 0) {
            return "";
        }
        BigInteger baseValue = BigInteger.valueOf(CHARS.length);
        BigInteger value = new BigInteger(1, input);
        StringBuilder sb = new StringBuilder();
        while (value.compareTo(BigInteger.ZERO) > 0) {
            BigInteger[] divmod = value.divideAndRemainder(baseValue);
            sb.insert(0, CHARS[divmod[1].intValue()]);
            value = divmod[0];
        }
        // 处理前导0字节
        for (byte b : input) {
            if (b == 0) {
                sb.insert(0, CHARS[0]);
            } else {
                break;
            }
        }
        return sb.toString();
    }

    /**
     * 解码为byte数组
     */
    public byte[] bytesDecode(String input) {
        if (input.isEmpty()) {
            return new byte[0];
        }
        BigInteger value = BigInteger.ZERO;
        BigInteger baseValue = BigInteger.valueOf(CHARS.length);
        for (char c : input.toCharArray()) {
            int digit = indexOf(c);
            if (digit == -1) {
                throw new IllegalArgumentException("Invalid Base58 character: " + c);
            }
            value = value.multiply(baseValue).add(BigInteger.valueOf(digit));
        }
        byte[] bytes = value.toByteArray();
        // 处理前导1字节（BigInteger可能添加的符号位）
        if (bytes.length > 1 && bytes[0] == 0) {
            byte[] tmp = new byte[bytes.length - 1];
            System.arraycopy(bytes, 1, tmp, 0, tmp.length);
            bytes = tmp;
        }
        // 处理前导0字节
        int leadingZeros = 0;
        for (char c : input.toCharArray()) {
            if (c == CHARS[0]) {
                leadingZeros++;
            } else {
                break;
            }
        }
        if (leadingZeros > 0) {
            byte[] tmp = new byte[bytes.length + leadingZeros];
            System.arraycopy(bytes, 0, tmp, leadingZeros, bytes.length);
            bytes = tmp;
        }
        return bytes;
    }

    public static void main(String[] args) {
        BaseCoder coder = new BaseCoder(
                "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz");

        long timestamp = System.currentTimeMillis() / 1000;
        System.out.println("原始时间戳: " + timestamp);

        String encoded = coder.encode(timestamp);
        System.out.println("Base62编码: " + encoded);

        long decoded = coder.decode(encoded);
        System.out.println("解码结果: " + decoded);

        UUID uuid = UUID.randomUUID();
        System.out.println("UUID: " + uuid);

        byte[] bytes = UUIDUtil.toBytes(uuid);
        encoded = coder.bytesEncode(bytes);
        System.out.println("编码: " + encoded);

        bytes = coder.bytesDecode(encoded);
        System.out.println("解码: " + UUIDUtil.fromBytes(bytes));
    }
}
